<template>
  <el-select :remote-method="handleRemote" @change="$emit('change', $event, renderList)">
    <div class="max-h-52 overflow-y-auto"
         v-infinite-scroll="handleLoad"
         clearable
         :infinite-scroll-immediate="false">
      <el-option v-for="item in renderList"
                 :key="item[optionAlias.value]"
                 :label="item[optionAlias.label]"
                 :value="item[optionAlias.value]">
        <slot :row="item" />
      </el-option>

      <div class="select-loading"
           v-loading="loading"
           element-loading-text="加载中"
           v-if="!isLoadedAll" />
    </div>
  </el-select>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue';
import { useTable } from "@/hooks";
import { isEqual, throttle } from "lodash-es";

interface IProps {
  options?: any[];
  optionAlias?: {
    label: string;
    value: string;
  };

  keyword?: string; // 远程搜索关键字字段
  defaultParams?: object; // 请求的静态参数
  server?: TRequestHookServer<any>; // 请求接口
  formatData?: (data: any[]) => any[]; // 对于数据复杂的，支持自定义过滤返回 {label,value}[]数据
}

defineEmits<{
  (e: "change", val: any, list: any[]): void
}>()

const props = withDefaults(defineProps<IProps>(), {
  keyword: "keyword",
  optionAlias: () => ({
    label: "label",
    value: "value",
  })
});

// @ts-expect-error
const { loading, list, search, pagination, isLoadedAll, run } = useTable<any, any>(props.server,
  {
    manual: !props.server,
    infinite: true,
    initialSearch: props.defaultParams,
    formatResult: props.formatData,
    initialPagination: {
      pageSize: 100
    }
  }
);

// 渲染下拉菜单列表
const renderList = computed(() =>
  list.value.length == 0 ? props.options : list.value
);

// 触底加载数据
const handleLoad = () => {
  if (isLoadedAll.value) return;
  run({
    page: pagination.currentPage + 1,
  });
};

const lastKeyword = ref(undefined)
// 处理远程搜索，页码置为1
const handleRemote = throttle((query: string) => {
  if (!loading || isEqual(lastKeyword.value, query)) return;
  search.value[props.keyword] = query
  run({ page: 1 });
}, 500);

</script>

<style lang="scss">
.select-loading {
  --el-loading-spinner-size: 16px;
  height: 24px;

  .el-loading-spinner {
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .el-loading-text {
    margin-left: 12px;
  }
}
</style>
